package cn.kgc.auth.service.impl;

import cn.kgc.auth.service.UserService;
import cn.kgc.auth.vo.PhoneApi;
import cn.kgc.dto.Dto;
import cn.kgc.mapper.UserMapper;
import cn.kgc.pojo.User;
import cn.kgc.utils.DtoUtils;
import cn.kgc.utils.Md5Utils;
import cn.kgc.utils.UUIDUtils;
import cn.kgc.vo.IlxToken;
import cn.kgc.vo.UserToken;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import springfox.documentation.spring.web.json.Json;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private SimpleMailMessage simpleMailMessage;
    @Resource
    private JavaMailSender javaMailSender;
    @Resource
    private PhoneApi phoneApi;
    /**
     * 判断用户是否存在
     * @param name
     * @return
     */
    @Override
    public Dto checkUserCode(String name) {
        User user=new User();
        user.setUsercode(name);
        int i=userMapper.selectCount(user);
        if (i>0){
            return DtoUtils.getFailDto("用户已存在，注册失败","30001");
        }
        return DtoUtils.getSuccessDto("用户名可用");
    }
    /**
     * 邮箱注册
     * @param user
     * @return
     */
    @Override
    public Dto registerByEmail(User user) {
        //添加激活状态和其他信息
        user.setActivated(0);
        user.setCreationdate(new Date());
        user.setModifydate(new Date());
        //密码加密
        user.setUserpassword(Md5Utils.enCode(user.getUserpassword()));
        if (!(userMapper.insert(user)>0)){
            return DtoUtils.getFailDto("添加失败，联系管理员","300002");
        }
        //发送验证码
        sendCode(user);
        return DtoUtils.getSuccessDto("注册成功，等待激活");
    }
    /**
     * 手机注册
     * @param user
     * @return
     */
    @Override
    public Dto registerByPhone(User user) {
        //添加激活状态和其他信息
        user.setActivated(0);
        user.setCreationdate(new Date());
        user.setModifydate(new Date());
        //密码加密
        user.setUserpassword(Md5Utils.enCode(user.getUserpassword()));
        if (!(userMapper.insert(user)>0)){
            return DtoUtils.getFailDto("添加失败，联系管理员","300003");
        }
        //发送验证码
        sendCode(user);
        return DtoUtils.getSuccessDto("注册成功，等待激活");
    }
    /**
     * 用户激活
     * @param user
     * @param code
     * @return
     */
    @Override
    public Dto userActivate(String user, String code) {
        //查看用户是否存在
        if (!stringRedisTemplate.hasKey(user)){
            return DtoUtils.getFailDto("用户已经激活或者激活码失效","300004");
        }
        //验证码比对
        if (!stringRedisTemplate.opsForValue().get(user).equals(code)){
            return DtoUtils.getFailDto("激活码错误","300005");
        }
        //修改用户激活状态
        User user1=new User();
        user1.setUsercode(user);
        user1=userMapper.selectOne(user1);
        user1.setActivated(1);
        int i=userMapper.updateByPrimaryKey(user1);
        if (i<1){
            return DtoUtils.getFailDto("激活失败","300006");
        }
        //删除redis的激活码
        stringRedisTemplate.delete(user);
        return DtoUtils.getSuccessDto("激活成功！");
    }

    /**
     * 登录
     * @param name 用户名
     * @param password 密码
     * @param logo 客户端标识
     * @return
     */
    @Override
    public Dto<UserToken> login(String name, String password,String logo) {
        User user=new User();
        user.setUsercode(name);
        user.setUserpassword(Md5Utils.enCode(password));
        user=userMapper.selectOne(user);
        if (ObjectUtils.isEmpty(user)){
            return DtoUtils.getFailDto("用户名或密码错误","300007");
        }
        if (user.getActivated()==0){
            return DtoUtils.getFailDto("用户未激活","300008");
        }
        //生成token
        IlxToken ilxToken=createToken(user,logo);
        return DtoUtils.getSuccessData(ilxToken,"登录成功");
    }

    /**
     * 注销
     * @param token
     * @return
     */
    @Override
    public Dto loginOut(String token) {
        if (!stringRedisTemplate.hasKey(token)){
            return DtoUtils.getFailDto("未登录，不用注销","300009");
        }
        stringRedisTemplate.delete(token);
        return DtoUtils.getSuccessDto("注销成功");
    }

    /**
     * token维护
     * @param token
     * @return
     */
    @Override
    public Dto reToken(String token) {
        if (!stringRedisTemplate.hasKey(token)){
            return DtoUtils.getFailDto("未登录或者token失效","300010");
        }
        String jsonToken=stringRedisTemplate.opsForValue().get(token);
        String tokenTime=token.substring(token.lastIndexOf("-")+1);
        long time=getTokenTime(tokenTime);
        //如果离过期大于30秒。
        if (new Date().getTime()-time<1770000){
            return DtoUtils.getFailDto("时间还长，无需维护","300011");
        }
        //维护token
        //1、延长token时间 stringRedisTemplate.expire();
        //2、生成新token，让前端使用
        //删除老token,客户端发请求时，还需要使用老token，所以不需要删除，让它自己过期
        //stringRedisTemplate.delete(token);
        //生成新token
        String logo="pc";
        if (!token.startsWith("token:pc")){
            logo="mobile";
        }
        IlxToken ilxToken=createToken(JSONObject.parseObject(jsonToken,User.class),logo);
        return DtoUtils.getSuccessData(ilxToken,"维护成功！");
    }
    //将时间转换成long
    private long getTokenTime(String tokenTime){
        SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmss");
        try {
            return sdf.parse(tokenTime).getTime();
        } catch (ParseException e) {
            return 0;
        }
    }
    //生成token并保存到redis
    private IlxToken createToken(User user, String logo) {
        String uuid=UUIDUtils.createUUID(6,true);
        Date date=new Date();
        String token="token:"+logo+"-"+Md5Utils.enCode(user.getUsercode())+"-"+user.getId()+uuid+"-"+getTime(date);
        //存入redis并设置时效
        int time=30;
        if (logo.equals("mobile")){
            time=Integer.MAX_VALUE;
        }
        stringRedisTemplate.opsForValue().set(token, JSON.toJSONString(user),time,TimeUnit.MINUTES);
        //返回token对象
        IlxToken ilxToken=new IlxToken();
        ilxToken.setToken(token);
        ilxToken.setGenTime(date.getTime());
        ilxToken.setExpTime(date.getTime()+time*60*1000);
        return ilxToken;
    }
    //时间
    private String getTime(Date date) {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmss");
        return sdf.format(date);
    }

    /**
     * 生成验证码并发送验证码
     * @param user
     */
    public void sendCode(User user){
        //邮箱发送验证码
        if (user.getUsercode().indexOf("@")!=-1){
            //生成验证码
            String code= UUIDUtils.createUUID();
            //保存验证码到redis
            stringRedisTemplate.opsForValue().set(user.getUsercode(),code,1*60*24, TimeUnit.MINUTES);
            //发送邮件
            simpleMailMessage.setText("欢迎注册爱旅行，您的验证码是"+code+"一天内有效，请尽快激活");
            simpleMailMessage.setTo(user.getUsercode());
            javaMailSender.send(simpleMailMessage);
        }else {//手机发送验证码
            //生成验证码
            Random random=new Random();
            String code= random.nextInt(10)+""+random.nextInt(10)+random.nextInt(10)+random.nextInt(10)+random.nextInt(10)+random.nextInt(10);
            //保存验证码到redis
            stringRedisTemplate.opsForValue().set(user.getUsercode(),code,2, TimeUnit.MINUTES);
            //发送短信验证
            phoneApi.sendTemplateSMS(user.getUsercode(),"1",new String[]{code,"2"});
        }
    }
}
